<template>
<div class="about">
  <h2>count: {{count}}</h2>
  <h2>msg: {{msg}}</h2>
  <h2>user: {{user}}</h2>
  <h2>numbers: {{numbers}}</h2>


  <button @click="update">更新</button>
</div>
</template>

<script lang="ts">
import {
  ref,
  reactive,
  toRefs,
  watch,
} from 'vue'

interface State {
  msg: String;
  user: {
    name: String,
    age?: Number   // age可以没有
  },
  numbers: number[]
}

export default {
  name: 'About',

  setup () {
    // 创建包含响应式数据ref对象
    const count = ref(1)

    // 创建一个包含多个数据的响应式对象
    // 返回的是包含多个数据的目标对象的代理对象
    // 可以通过代理对象来更新目标对象的数据 ==> 界面就会自动更新
    const state = reactive<State>({
      msg: 'abc',
      user: {
        name: 'tom',
      },
      numbers: [1, 3, 5]
    })
    console.log(state)

    const update = () => {
      // state.msg += '--'
      // state.user.name += '--'
      /* 
      直接添加新属性 
        在vue2中界面不会更新
        在vue3中界面会更新
      */
      // state.user.age = 12 
      // state.numbers.push(7)
      /* 
      通过下标直接给数组添加元素
        在vue2中界面不会更新
        在vue3中界面会更新
      */
      // state.numbers[3] = 8

      count.value++
      // state.msg += '--'
    }

    // toRefs: 将state中每个属性都转换成ref响应式对象, 返回包含它们的新对象
    // console.log(toRefs(state))

    // 监视ref
    watch(count, (newValue, oldValue) => {
      console.log('count变化了', newValue, oldValue)
    }, {deep: true, immediate: true})

    // 监视state中的某个数据
    watch(() => state.msg, (newValue, oldValue) => {
      console.log('msg变化了', newValue, oldValue)
    })

    // 监视多个数据
    watch([count, () => state.msg], (newValues, oldValues) => {
      console.log('count或msg变化了', newValues, oldValues)
    })

    

    return { // 返回对象中的所有属性, 模板可以直接读取显示
      count,
      // state,
      // ...state, // 直接取出state中的数据, 不再是响应式的
      ...toRefs(state),
      update
    }
  }
}
</script>
